
import requests
from typing import Any, Dict, List
from .base_tool import BaseTool, ToolResult
from config import Config


class WebSearchTool(BaseTool):
    """Tool for searching the web using various search APIs."""
    
    def __init__(self):
        super().__init__(
            name="web_search",
            description=self._get_detailed_description()
        )
        self.serper_api_key = Config.SERPER_API_KEY
    
    def _get_detailed_description(self) -> str:
        """Get detailed description with examples for web search operations."""
#         return """Search the web for current information, news, and real-time data using advanced search APIs.
#
# WHAT IT DOES:
# • Searches the internet for up-to-date information
# • Returns relevant web pages, articles, and resources
# • Provides real-time data and current events
# • Finds information not available in static databases
#
# SEARCH TYPES:
# • General Search: Find web pages, articles, documentation
#   Examples: "latest AI developments", "Python programming tutorial"
#
# • News Search: Current events, breaking news, recent updates
#   Examples: "today's news", "stock market updates", "weather forecast"
#
# • Technical Information: Documentation, APIs, code examples
#   Examples: "React hooks documentation", "MySQL syntax guide"
#
# • Product Information: Reviews, comparisons, specifications
#   Examples: "iPhone 15 review", "best laptops 2024"
#
# BEST USE CASES:
# • Current events and breaking news
# • Real-time data (stock prices, weather, sports scores)
# • Recent developments in technology, science, politics
# • Product reviews and comparisons
# • Technical documentation and tutorials
# • Finding specific websites or resources
#
# USAGE EXAMPLES:
# - Current events: "Ukraine war latest news"
# - Technical info: "Docker compose tutorial"
# - Product research: "best electric cars 2024"
# - Real-time data: "Bitcoin price today"
# - Specific searches: "OpenAI GPT-4 capabilities"
#
# SEARCH STRATEGIES:
# • Use specific keywords for better results
# • Include time indicators for recent info ("2024", "latest", "recent")
# • Use quotes for exact phrases: "climate change effects"
# • Add context for ambiguous terms
# • Combine multiple relevant keywords
#
# RETURNED INFORMATION:
# - Page titles and descriptions
# - URLs for full articles
# - Publication dates when available
# - Relevance rankings
# - Related search suggestions
#
# ADVANTAGES OVER OTHER TOOLS:
# • More current than Wikipedia
# • Broader coverage than academic databases
# • Real-time information updates
# • Access to diverse sources and perspectives
# • Technical documentation and tutorials"""

        return """使用高级搜索API搜索网络上的当前信息、新闻和实时数据。
        
功能：
- 在互联网上搜索最新信息
- 返回相关网页、文章和资源
- 提供实时数据和时事
- 查找静态数据库中没有的信息

搜索类型：
- 通用搜索：查找网页、文章、文档
  示例：“最新人工智能发展”、“Python编程教程”

- 新闻搜索：时事、突发新闻、最新更新
  示例：“今日新闻”、“股市更新”、“天气预报”

- 技术信息：文档、API、代码示例
  示例：“React钩子文档”、“MySQL语法指南”

- 产品信息：评论、比较、规格
  示例：“iPhone 15评测”、“2024年最佳笔记本电脑”

最佳使用场景：
- 时事和突发新闻
- 实时数据（股票价格、天气、体育比分）
- 技术、科学、政治领域的最新发展
- 产品评论和比较
- 技术文档和教程
- 查找特定网站或资源

使用示例：
- 时事：“乌克兰战争最新消息”
- 技术信息：“Docker compose教程”
- 产品研究：“2024年最佳电动汽车”
- 实时数据：“今日比特币价格”
- 特定搜索：“OpenAI GPT-4功能”

搜索策略：
- 使用特定关键词以获得更好的结果
- 包含时间指示词以获取近期信息（“2024年”、“最新”、“最近”）
- 对确切短语使用引号：“气候变化影响”
- 为模糊术语添加上下文
- 组合多个相关关键词

返回的信息：
- 页面标题和描述
- 完整文章的URL
- 可用的发布日期
- 相关性排名
- 相关搜索建议

相对于其他工具的优势：
- 比维基百科更及时
- 比学术数据库覆盖范围更广
- 实时信息更新
- 可获取多样化的来源和观点
- 技术文档和教程"""

    async def execute(self, query: str, **kwargs) -> ToolResult:
        """Execute web search."""
        try:
            # Get optional parameters
            num_results = kwargs.get("num_results", 5)
            search_type = kwargs.get("search_type", "search")  # search, news, images
            
            if self.serper_api_key:
                return await self._search_with_serper(query, num_results, search_type)
            else:
                # Fallback to a simple mock search if no API key
                return await self._mock_search(query, num_results)
        
        except Exception as e:
            return ToolResult(
                success=False,
                data=None,
                error=f"Web search failed: {str(e)}"
            )
    
    async def _search_with_serper(self, query: str, num_results: int, search_type: str) -> ToolResult:
        """Search using Serper API."""
        try:
            url = f"https://google.serper.dev/{search_type}"
            headers = {
                "X-API-KEY": self.serper_api_key,
                "Content-Type": "application/json"
            }
            payload = {
                "q": query,
                "num": num_results
            }
            
            response = requests.post(url, headers=headers, json=payload, timeout=10)
            response.raise_for_status()
            
            data = response.json()
            
            # Extract results based on search type
            if search_type == "search":
                results = self._extract_search_results(data)
            elif search_type == "news":
                results = self._extract_news_results(data)
            else:
                results = self._extract_search_results(data)
            
            return ToolResult(
                success=True,
                data={
                    "query": query,
                    "results": results,
                    "total_results": len(results)
                },
                metadata={
                    "search_type": search_type,
                    "num_results": num_results,
                    "provider": "serper"
                }
            )
        
        except requests.RequestException as e:
            return ToolResult(
                success=False,
                data=None,
                error=f"Serper API request failed: {str(e)}"
            )
        except Exception as e:
            return ToolResult(
                success=False,
                data=None,
                error=f"Serper search failed: {str(e)}"
            )
    
    async def _mock_search(self, query: str, num_results: int) -> ToolResult:
        """Mock search results when no API key is available."""
        mock_results = [
            {
                "title": f"'{query}'的模拟检索结果 1",
                "link": "https://example.com/result1",
                "snippet": f"这是针对查询“{query}”的模拟搜索结果。在实际应用中，它应该包含来自网络的真实搜索结果。"
            },
            {
                "title": f"'{query}'的模拟检索结果 2",
                "link": "https://example.com/result2", 
                "snippet": f"另一个针对“{query}”的模拟结果。这展示了网络搜索工具返回结构化数据的方式。"
            },
            {
                "title": f"'{query}'的模拟检索结果 3'",
                "link": "https://example.com/result3",
                "snippet": f"第三个针对“{query}”的模拟结果。请在您的.env文件中配置SERPER_API_KEY以获取真实搜索结果。"
            }
        ]
        
        # Limit results to requested number
        results = mock_results[:num_results]
        
        return ToolResult(
            success=True,
            data={
                "query": query,
                "results": results,
                "total_results": len(results),
                "note": "这些是模拟结果。请设置SERPER_API_KEY以获取真实的网络搜索结果。"
            },
            metadata={
                "search_type": "mock",
                "num_results": num_results,
                "provider": "mock"
            }
        )
    
    def _extract_search_results(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
        """Extract search results from Serper response."""
        results = []
        
        # Extract organic results
        for item in data.get("organic", []):
            results.append({
                "title": item.get("title", ""),
                "link": item.get("link", ""),
                "snippet": item.get("snippet", ""),
                "position": item.get("position", 0)
            })
        
        # Extract knowledge graph if available
        if "knowledgeGraph" in data:
            kg = data["knowledgeGraph"]
            results.insert(0, {
                "title": f"Knowledge Graph: {kg.get('title', '')}",
                "link": kg.get("website", ""),
                "snippet": kg.get("description", ""),
                "type": "knowledge_graph"
            })
        
        return results
    
    def _extract_news_results(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
        """Extract news results from Serper response."""
        results = []
        
        for item in data.get("news", []):
            results.append({
                "title": item.get("title", ""),
                "link": item.get("link", ""),
                "snippet": item.get("snippet", ""),
                "date": item.get("date", ""),
                "source": item.get("source", ""),
                "type": "news"
            })
        
        return results
    
    def get_schema(self) -> Dict[str, Any]:
        """Get the tool's input schema."""
        # return {
        #     "type": "object",
        #     "properties": {
        #         "query": {
        #             "type": "string",
        #             "description": "Search query to find information on the web"
        #         },
        #         "num_results": {
        #             "type": "integer",
        #             "description": "Number of search results to return (default: 5)",
        #             "default": 5,
        #             "minimum": 1,
        #             "maximum": 20
        #         },
        #         "search_type": {
        #             "type": "string",
        #             "description": "Type of search to perform",
        #             "enum": ["search", "news", "images"],
        #             "default": "search"
        #         }
        #     },
        #     "required": ["query"]
        # }

        return {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "用于网络信息检索的查询语句"
                },
                "num_results": {
                    "type": "integer",
                    "description": "要返回的搜索结果数量（默认值：5）",
                    "default": 5,
                    "minimum": 1,
                    "maximum": 20
                },
                "search_type": {
                    "type": "string",
                    "description": "待检索类型",
                    "enum": ["search", "news", "images"],
                    "default": "search"
                }
            },
            "required": ["query"]
        }